﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CS_BEGINNER_TO_PROFICIENT.STD.DelegatedSTD
{
    public delegate void TaskCompletedHandler<T>(T result);

    public class Task<T>
    {
        public event TaskCompletedHandler<T> Completed;
        private readonly Func<T> _taskFunc;

        public Task(Func<T> taskFunc)
        {
            _taskFunc = taskFunc;
        }

        public async void Execute()
        {
            await Task.Run(() =>
            {
                var res = _taskFunc();
                OnCompleted(res);
            });
        }

        protected virtual void OnCompleted(T result)
        {
            Completed?.Invoke(result);
        }
    }

    public class TaskScheduler
    {
        public void Register<T>(Task<T> task, TaskCompletedHandler<T> handler)
        {
            task.Completed += handler;
        }

        public void UnRegister<T>(Task<T> task, TaskCompletedHandler<T> handler)
        {
            task.Completed -= handler;
        }
    }

    public class TaskHandler
    { 
        public void HandleTaskCompletion(int res)
        {
            Console.WriteLine($"Task completed with result: {res}");
        }
    }

    public class DelegatedSTDP16
    {
        public static void Execute()
        {
            TaskScheduler scheduler = new TaskScheduler();
            TaskHandler handler = new TaskHandler();

            var task = new Task<int>(() =>
            {
                System.Threading.Thread.Sleep(1000);
                return 42;
            });

            scheduler.Register(task, handler.HandleTaskCompletion);
            task.Execute();
            System.Threading.Thread.Sleep(5000);
        }
    }
}
